# 22. 内置函数进阶


# lamda匿名函数

是为了解决一些简单的需求面设计的一句话函数

lambda表示的是匿名函数,不需要用def来声明,一句话就可以声明出一个函数

注意:

  1. 函数的参数可以有多少,多少参数之间用逗号隔开
  2. 匿名函数不管多复杂,只能写一行,且逻辑结束直接返回数据
  3. 返回值和正常的函数一样,可以是任意数据类型
  4. 他只能使用return来返回数据

语法:函数名 = lambda 参数: 返回值

so = lambda n: n * n
print(so(3))

执行结果:
9

# 查看函数名 name()

匿名函数并不是说一定没有名字,前面的变量就是一个函数名,那为什么说他是匿名呢,原因就是通过__name__查看的时候是没有名字的,统一叫 lambda,在调用的时候没有什么特别之处,跟正常的函数差不多,正常函数调用即可

so = lambda n: n * n
def wo(n):
    return n * n
print(so(9))
print(so.__name__)
print(wo(9))
print(wo.__name__)

执行结果:
81
<lambda>
81
wo


# sorted()-排序函数

排序函数,在列表中也有一个内置函数sort(),但这个函数只能对列表类型使用,而sorted是面对所有类型

注意:sorted实际是通过数字来排序的,无论你自定义的排序规则是什么,都要给他数字的结果才能排序

语法格式:

sorted(iterable,key=None,reverse=False)

iterable:可迭代对象,表示要进行排序操作的数据类型需要可迭代的
key:排序规则(排序函数),在sorted内部会将可迭代对象中的每一个元素传递给这个函数的参数,根据函数运算的结果进行排序,默认是:为空
reverse:是否倒序:True:倒序,False:正序 ,默认是正序 

# 来个简单的排序

so = [1,4,0,5,2,6,8,9,3]
so = sorted(so)
print(so)

执行结果:
[0, 1, 2, 3, 4, 5, 6, 8, 9]

​ 为什么不用写,key跟reverse参数,因为这二个都有默认值,如果不使用系统会默认使用默认值


# 在来个字典排序

so = {1:"江",3:"小",2:"凡"}
so = sorted(so)
print(so)

执行结果:
[1, 2, 3]

​ 如果使用默认的key排序规则,是无法排序字典的value值


# 使用自定义的排序规则

排序规则实际是写好的函数,在把函数名放在key中

so = ["技术部","人力行政部","商业务部","财务内帐外帐部"]
def wo(n):
    return len(n)
eo = sorted(so, key=wo)
print(eo)

执行结果:
['技术部', '商业务部', '人力行政部', '财务内帐外帐部']

# 模拟运行机制

模拟上一次实例的sorted运行机制

so = ["技术部","人力行政部","商业务部","财务内帐外帐部"]
def wo(n):
    return len(n)
eo = sorted(so, key=wo)
print(eo)

## 内部大概是这样运行的
for i in so:
    wo(i)

​ 使用for循环,循环要排序的数据,一个一个拿出来,放在自定好的函数中,得到数字,在进行排序


# 用lambda来使用

so = ["技术部","人力行政部","商业务部","财务内帐外帐部"]
wo = lambda n : len(n)
eo = sorted(so, key=wo)
print(eo)

so = ["技术部","人力行政部","商业务部","财务内帐外帐部"]
eo = sorted(so, key=lambda n : len(n))
print(eo)

执行结果:
['技术部', '商业务部', '人力行政部', '财务内帐外帐部']
['技术部', '商业务部', '人力行政部', '财务内帐外帐部']

# 练习题

最后用练习题来结尾

要求:把下面的学习信息按年龄进行顺序

so = [
    {"id":1, "name":"张一","age":"17"},
    {"id":2, "name":"王二","age":"20"},
    {"id":3, "name":"陈三","age":"18"},
    {"id":4, "name":"李四","age":"22"},
    {"id":5, "name":"赵五","age":"19"},
    {"id":6, "name":"孙六","age":"16"}
]

答案

so = [
    {"id":1, "name":"张一","age":"17"},
    {"id":2, "name":"王二","age":"20"},
    {"id":3, "name":"陈三","age":"18"},
    {"id":4, "name":"李四","age":"22"},
    {"id":5, "name":"赵五","age":"19"},
    {"id":6, "name":"孙六","age":"16"}
]
##第一种
def wo(n):
    return n["age"]
for i in sorted(so,key=wo):
    print(i)
##第二种 
for i in sorted(so,key=lambda n: n["age"]):
    print(i)

执行结果:
{'id': 6, 'name': '孙六', 'age': '16'}
{'id': 1, 'name': '张一', 'age': '17'}
{'id': 3, 'name': '陈三', 'age': '18'}
{'id': 5, 'name': '赵五', 'age': '19'}
{'id': 2, 'name': '王二', 'age': '20'}
{'id': 4, 'name': '李四', 'age': '22'}

​ 如果不使用for循环也可以,就会出现一个列表,所有数据都在列表中,看着太乱了



# filter() - 筛选函数

筛选函数,也是要自定义筛选规则

筛选出来结果的是迭代器

语法格式:

filter(function,iterable)

function:用于筛选的函数,在filer中会自动的把iterable中的元素传递给function,然后根据function返回的TrueFalse来判断是否保留此项数据
iterable:可以迭代对象

# 来个简单的筛选

so = [1,2,3,4,5,6,7,8,9]
wo = filter(lambda n: n % 2 == 1,so)
print(list(wo))

执行结果:
[1, 3, 5, 7, 9]

​ 以上实例:筛选出来的结果是迭代器,所以要么用__next__等方式执行,或用list列表函数来执行


# 模拟运行机制

so = [1,2,3,4,5,6,7,8,9]
def eo(n):
    return n % 2 == 1
wo = filter(eo,so)
print(list(wo))

## 内部大概运行机制
for i in so:
    eo(i)
    

​ 使用for循环获取要筛选的数据,一个一个在给写好的函数规则筛选,Ture就返回数据,False就过滤数据


# 练习题

最后也来个练习题结尾

要求:将以下的学生信息大于等于20岁的筛选出来

so = [
    {"id":1, "name":"张一","age":"17"},
    {"id":2, "name":"王二","age":"20"},
    {"id":3, "name":"陈三","age":"18"},
    {"id":4, "name":"李四","age":"22"},
    {"id":5, "name":"赵五","age":"19"},
    {"id":6, "name":"孙六","age":"16"}
]

答案

so = [
    {"id":1, "name":"张一","age":"17"},
    {"id":2, "name":"王二","age":"20"},
    {"id":3, "name":"陈三","age":"18"},
    {"id":4, "name":"李四","age":"22"},
    {"id":5, "name":"赵五","age":"19"},
    {"id":6, "name":"孙六","age":"16"}
]

## 第一种
wo = filter(lambda i: int(i["age"]) >= 20,so)
print(list(wo))

## 第二种
for i in filter(lambda i: int(i["age"]) >= 20,so):
    print(i)

执行结果:
{'id': 2, 'name': '王二', 'age': '20'}
{'id': 4, 'name': '李四', 'age': '22'}

​ 如果不使用for循环也可以,就会出现一个列表,所有数据都在列表中,看着太乱了



# map() - 映射函数

映射函数

语法格式:

map(function,iterable)

function:可以对可迭代对象中的每一个元素进行映射,分别取执行function
iterable:可以迭代对象

# 来个简单的筛选

计算列表中每个元素的平方,返回新列表

eo = [1,2,3,4,5,6,7,8,9]
def so(n):
    return n * n
wo = map(so,eo)
print(list(wo))

执行结果:
[1, 4, 9, 16, 25, 36, 49, 64, 81]

​ 以上实例:筛选出来的结果是迭代器,所以要么用__next__等方式执行,或用list列表函数来执行


# 用lambda来使用

eo = [1,2,3,4,5,6,7,8,9]
print(list(map(lambda n: n * n ,eo)))

执行结果:
[1, 4, 9, 16, 25, 36, 49, 64, 81]

# 练习题

最后也来个练习题来结尾

要求:计算以下有个列表中相同位置的数据的和

so = [1,10,20,12,5,7,53]
wo = [8,21,25,10,27,84]

答案

so = [1,10,20,12,5,7,53]
wo = [8,21,25,10,27,84]
print(list(map(lambda i,n: i + n ,so,wo)))

执行结果:
[9, 31, 45, 22, 32, 91]


# 递归函数

递归,递归就是在函数中调用函数的本身的就叫做递归

如果在函数中不断的调用递归,这会让内存无限的生成函数空间来存储,可能会让系统卡死

Python解释器为了解决无限递归,限制了递归次数

在Python官方文档显示递归次数不高于1000,实测是998

递归的应用:可以使用递归来遍历各种树形结构,比如文件系统


# 使用递归来遍历文件系统


# 需要的模块跟函数


# 模块

需要使用os模块来遍历文件系统


# 函数

os.listdir(链接路径)
	##获取到当前文件夹中的所有文件目录
os.path.join(旧链接路径,新链接路径)
	##拼接文件链接,比如获取到一个文件目录链接,但是下面还有目录,就需要这个函数来把二个链接拼接起来
os.path.isdir(链接路径)
	##判断该链接路径是文件目录还是文件,目录为:True,文件为:False

# 遍历文件系统

import os
lo = "E:\so"
def so(ls,n):
    wo = os.listdir(ls)
    for i in wo:
        ll = os.path.join(ls,i)
        if os.path.isdir(ll):
            print("\t" * n,"L"*n,i)
            so(ll,n + 1)
        else:
            print("\t" * n,"L"*n,i)
so(lo,0)

# 这是一个相对简单的遍历递归
导入os模块
定义要查询的文件路径赋值给变量lo
定义函数,定义二个参数,ls:获取文件路径,n:用于区分显示效果
	使用os.listdir()函数,打开该路径显示的内容,并赋值给变量wo
	使用for循环来遍历变量wo
		使用os.path.join()函数来对参数ls跟循环的i进行拼接,并赋值给变量ll
		使用if判断来对os.path.isdir()判断ll 路径是否是目录还是文件
			打印,这行不用解释了吧!!!
			因判断是目录,那目录下可能会还有文件或目录,那么需要使用递归
		如果是文件
			打印,这行不用解释了吧!!!
执行函数,传递参数


# 二分查找(算法初始)

二分查找,每次能够排除掉一半的数据,查找的效率非常高,但是局限性比较大,必须是有序序列才可以使用二分查找

简单说,就是掐头结尾取中间. 不停的改变左和右. 间接改变中间

如果是初学者会比较难理解,但是最好能理解-


# 二分查找 - 非递归算法

lst = [11,22,33,44,55,66,77,88,99,123,234,345,456,567,678,789,1111]
so = 77
le = 0
re = len(lst) - 1
eo = 1
while le <= re:
    wo = (le + re) // 2
    if so > lst[wo]:
        le = wo + 1
    elif so < lst[wo]:
        re = wo - 1
    else:
        print("查找的内容在该列表的第:",wo,"位")
        print("经过第",eo,"算法查找")
        break
    eo += 1

## 一个很简单的二分查找算法
一个要查找的列表
变量so:要查找的值
变量le:开头值
变量re:结尾值
变量eo:记录循环次数值
while循环,判断le变量是否小于或等于re变量	
	取中间取,怎么取,把开关值跟结尾值相加在除2,因为要得到整数所以要整除// 在赋值给变量
	判断查询值是否大于中间值的元素
		如果大于,那就证明要的值在右边,需要对开头值进行位置的重新赋值,切掉左边的数据
	使用elif判断查询值是否小于中间值的元素
		如果小于,那就证明要的值在左边,需要对结尾值进行位置的重新赋值,切掉右边的数据
	如果以上判断都不生效
    	 打印中间值
    	 接下来就不用说明了吧!!!
     记录值变量+1,效果每次循环记录

# 二分查找 - 非递归算法 - 找出口

如果要查找的值不在数据列表中,那要怎么办

lst = [11,22,33,44,55,66,77,88,99,123,234,345,456,567,678,789,1111]
so = 77
le = 0
re = len(lst) - 1
eo = 1
while le <= re:
    if lst.count(so) == 0:
        print(-1)
        break
    wo = (le + re) // 2
    if so > lst[wo]:
        le = wo + 1
    elif so < lst[wo]:
        re = wo - 1
    else:
        print("查找的内容在该列表的第:",wo,"位")
        print("经过第",eo,"算法查找")
        break
    eo += 1

# 二分查找 - 使用递归

lst = [11,22,33,44,55,66,77,88,99,123,234,345,456,567,678,789,1111]
def so(eo,le,re,n=1):
    if le <= re:
        wo = (le + re) // 2
        if eo > lst[wo]:
            le = wo + 1
        elif eo < lst[wo]:
            re = wo - 1
        else:
            print("查找的内容在该列表的第:",wo,"位")
            print("经过第", n, "算法查找")
            return
        return so(eo,le,re,n+1)
    else:
        print(-1)
        return
so(77,0,len(lst) - 1)